#include <stdint.h>
#include <string>
#include <memory>
#include <sstream>
#include <stdarg.h>
#include <stdlib.h>
class Logger;
class LoggerManager;

namespace sylar {
/**
 * @brief 日志级别
 * 
 */
class LogLevel {
public:
    enum Level {
        /// @brief 未知
        UNKNOW = 0,
        /// @brief debug
        DEBUG = 1,
        /// @brief 信息
        INFO = 2,
        /// @brief 警告
        WARN = 3,
        /// @brief 错误
        ERROR = 4,
        /// @brief 致命错误
        FATAL = 5,
    };
    /// @brief 将日志级别转成文本输出
    /// @param level 日志级别
    /// @return 输出文本
    static const char* ToString(LogLevel::Level level);
    
    /// @brief 将文本转换成日志级别
    /// @param str 日志文本
    /// @return 日志级别
    static LogLevel::Level FromString(const std::string& str);
};


/// @brief 日志事件
class LogEvent {
public:
    typedef std::shared_ptr<LogEvent> ptrLogEvent;

    /// @brief LogEvent的构造函数
    /// @param Logger 日志器
    /// @param level 日志级别
    /// @param file 文件名
    /// @param line 文件行号
    /// @param elapse 程序起到依赖的耗时(ms)
    /// @param thread_id 线程id
    /// @param coroutine_id 协程id
    /// @param time 日志时间(s)
    /// @param thread_name 线程名称
    LogEvent(std::shared_ptr<Logger> Logger, LogLevel::Level level, const char* file, int32_t line, uint32_t elapse,
        uint32_t thread_id, uint32_t coroutine_id, uint64_t time, const std::string& thread_name);
    
    /// @brief 返回文件名
    const char* getFile() const { return m_file; }
    
    /// @brief 返回行号
    int32_t getLine() const { return m_line; }
    
    /// @brief 返回耗时
    uint32_t getElapse() const { return m_elapse; }

    /// @brief 返回线程id
    uint32_t getThreadId() const { return m_threadId; }
    
    /// @brief 返回协程id
    uint32_t getCoroutineId() const { return m_coroutineId; }
    
    /// @brief 返回时间
    uint64_t getTime() const { return m_time; }

    /// @brief 返回线程名称
    const std::string& getThreadName() const { return m_threadName; }
    
    /// @brief 返回日志内容
    std::string getContent() const { return m_ss.str(); }
    
    /// @brief 返回日志器
    std::shared_ptr<Logger> getLogger() const { return m_logger; }
    
    /// @brief 返回日志级别
    LogLevel::Level getLevel() const { return m_level; }
    
    /// @brief 返回日志内容字符串流
    std::stringstream& getSS() { return m_ss; }

    /// @brief 格式化写入日志内容
    /// @param fmt 日志内容
    void format(const char* fmt, ...);
    
    /// @brief 格式化写入日志内容
    /// @param fmt 日志内容
    /// @param al 可变参数
    void format(const char* fmt, va_list al);
private:
    /// @brief 替换Linux下的拓展函数vasprintf
    /// @param buf 
    /// @param fmt 
    /// @param args 
    /// @return 
    int __vasprintf(char** buf, const char* fmt, va_list args);

    /// @brief 文件名
    const char* m_file = nullptr;
    /// @brief 行号
    int32_t m_line = 0;
    /// @brief 程序启动开始到现在的毫秒数
    uint32_t m_elapse = 0;
    /// @brief 线程id
    uint32_t m_threadId = 0;
    /// @brief 协程id
    uint32_t m_coroutineId = 0;
    /// @brief 时间戳
    uint64_t m_time = 0;
    /// @brief 线程名
    std::string m_threadName;
    /// @brief 日志内容流
    std::stringstream m_ss;
    /// @brief 日志器
    std::shared_ptr<Logger> m_logger;
    /// @brief 日志等级
    LogLevel::Level m_level;
};

/// @brief 日志事件包装器
class LogEventWrap {
public:
    /// @brief 构造函数
    /// @param e 日志事件
    LogEventWrap(LogEvent::ptrLogEvent e);
    
    /// @brief 析构函数
    ~LogEventWrap();

    /// @brief 获取日志事件
    LogEvent::ptrLogEvent getEvent() const { return m_event; }
    
    /// @brief 获取日志内容流
    std::stringstream& getSS();
private:
    /// @brief 日志事件
    LogEvent::ptrLogEvent m_event;
    
};

}
